package org.shunya.duplicatefileperquisitor.gui;

import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Region;
import javafx.util.Callback;
import org.shunya.duplicatefileperquisitor.model.File;

import java.io.IOException;
import java.net.InetAddress;
import java.net.URL;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;

import static java.nio.file.Files.newInputStream;

public class DuplicateFilePerquisitorController extends AnchorPane implements Initializable {

    @FXML
    TreeView systemTree;
    @FXML
    Button addBtn;
    @FXML
    Button removeBtn;
    @FXML
    Button clearBtn;
    @FXML
    Tab includeToScanTab;
    @FXML
    ListView<FilePathTreeItem> includeToScanList;
    @FXML
    Tab excludeFromScanTab;
    @FXML
    ListView<FilePathTreeItem> excludeFromScanList;
    @FXML
    TextField includeFileTypesTxt;
    @FXML
    TextField excludeFileTypesTxt;
    @FXML
    Button includeFileTypesBtn;
    @FXML
    Button excludeFileTypesBtn;
    @FXML
    Button scanBtn;
    @FXML
    ProgressBar progressBar;
    @FXML
    Region region;
    @FXML
    TableView<File> resultTable;
    @FXML
    TableColumn<File, Boolean> checkBoxColumn;
    @FXML
    TableColumn fileNameColumn;
    @FXML
    TableColumn filePathColumn;
    @FXML
    TableColumn groupColumn;
    @FXML
    Button selectDuplicatesBtn;
    @FXML
    Button processDuplicatesBtn;
    @FXML
    TextField filesScannedField;
    @FXML
    TextField duplicateFilesField;
    @FXML
    TextField originalFilesField;
    @FXML
    TextField selectedField;
    @FXML
    Label timeElapsedLbl;
    @FXML
    Label processingLbl;
    @FXML
    Button allFilesBtn;
    @FXML
    Button archivesBtn;
    @FXML
    Button documentsBtn;
    @FXML
    Button musicBtn;
    @FXML
    Button picturesBtn;
    @FXML
    Button videosBtn;
    @FXML
    Button othersBtn;
    private DuplicateFilePerquisitorMain application;

    public void setApplication(DuplicateFilePerquisitorMain application) {
        this.application = application;
    }

    public void onAddBtnActionEvent() {
        ObservableList<FilePathTreeItem> items = systemTree.getSelectionModel().getSelectedItems();
        if (includeToScanTab.isSelected()) {
            includeToScanList.getItems().addAll(items);
        } else if (excludeFromScanTab.isSelected()) {
            excludeFromScanList.getItems().addAll(items);
        }
    }

    public void onRemoveBtnActionEvent() {
        if (includeToScanTab.isSelected()) {
            removeItemsFromList(includeToScanList);
        } else if (excludeFromScanTab.isSelected()) {
            removeItemsFromList(excludeFromScanList);
        }
    }

    public void onClearBtnActionEvent() {
        includeToScanList.getItems().remove(0, includeToScanList.getItems().size());
        excludeFromScanList.getItems().remove(0, excludeFromScanList.getItems().size());
    }

    public void onScanBtnActionEvent() {
        region.setStyle("-fx-background-color: rgba(0, 0, 0, 0.4)");
        FileScanningService fileScanningService = new FileScanningService(this);
        progressBar.progressProperty().bind(fileScanningService.progressProperty());
        region.visibleProperty().bind(fileScanningService.runningProperty());
        progressBar.visibleProperty().bind(fileScanningService.runningProperty());
        resultTable.itemsProperty().bind(fileScanningService.valueProperty());
        fileScanningService.start();
    }

    public void onSelectDuplicateBtnActionEvent() {
        Integer group = -1;
        ObservableList<File> items = resultTable.getItems();
        Collections.sort(items);
        int selectedFilesCount = 0;
        for (File file : items) {
            if (group == -1 || !group.equals(file.getGroup())) {
                group = file.getGroup();
            } else {
                file.setSelected(true);
                selectedFilesCount++;
            }
        }
        selectedField.setText(selectedFilesCount + "");
    }

    public void onProcessDuplicateBtnActionEvent() {
        ObservableList<File> items = resultTable.getItems();
        for (File file : items) {
            if (file.isSelected()) {
                try {
//                    java.io.File[] files1 = {file.getPath().toFile()};
//                    W32FileUtils.getInstance().moveToTrash(files1);
                    Files.deleteIfExists(file.getPath());
                    items.remove(file);
                } catch (IOException e) {

                }
            }
        }
    }

    public void onIncludeFileTypesBtnEvent() {
        try {
            application.gotoFileTypes(includeFileTypesTxt);
        } catch (Exception e) {

        }
    }

    public void onExcludeFileTypesBtnEvent() {
        try {
            application.gotoFileTypes(excludeFileTypesTxt);
        } catch (Exception e) {

        }
    }

    public void onAllFilesBtnActionEvent() {

    }

    public void onArhivesBtnActionEvent() {

    }

    public void onDocumentsBtnActionEvent() {

    }

    public void onMusicBtnActionEvent() {

    }

    public void onPicturesBtnActionEvent() {

    }

    public void onVideosBtnActionEvent() {

    }

    public void onOthersBtnActionEvent() {

    }

    private void intializeResultTable() {

        checkBoxColumn.setCellValueFactory(new PropertyValueFactory<File, Boolean>("selected"));

        checkBoxColumn.setCellFactory(new Callback<TableColumn<File, Boolean>, TableCell<File, Boolean>>() {
            public TableCell<File, Boolean> call(TableColumn<File, Boolean> p) {
                CheckBoxTableCell<File, Boolean> cell = new CheckBoxTableCell<>();
                cell.setAlignment(Pos.CENTER);
                return cell;
            }
        });

        fileNameColumn.setCellValueFactory(new PropertyValueFactory<File, String>("fileName"));
        fileNameColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        filePathColumn.setCellValueFactory(new PropertyValueFactory<File, String>("filePath"));
        filePathColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        groupColumn.setCellValueFactory(new PropertyValueFactory<File, Integer>("group"));
        groupColumn.setCellFactory(new Callback<TableColumn<File, Integer>, TableCell<File, Integer>>() {
            @Override
            public TableCell call(final TableColumn<File, Integer> group) {
                return new TextFieldTableCell<File, Integer>() {
                    @Override
                    public void updateItem(Integer i, boolean b) {
                        i = i == null ? 0 : i;
                        this.getStyleClass().add(i % 2 == 0 ? "even" : "odd");
                        this.setText(i == 0 ? "" : i.toString());
                    }
                };
            }
        });
        resultTable.setEditable(true);
    }

    private void removeItemsFromList(ListView<FilePathTreeItem> listView) {
        final ObservableList<FilePathTreeItem> selectedIds = listView.getSelectionModel().getSelectedItems();
        while(selectedIds.get(0) != null) {
            listView.getItems().remove(selectedIds.get(0));
        }
    }

    public void systemTreeHandler() {
        FilePathTreeItem selectedItem = (FilePathTreeItem) systemTree.getSelectionModel().getSelectedItem();
        if (selectedItem != null && selectedItem.isDirectory() && !selectedItem.isExpanded())
            selectedItem.handleBranchExpandedEvent(selectedItem);
        else if (selectedItem != null && selectedItem.isDirectory() && selectedItem.isExpanded())
            selectedItem.handleBranchCollapsedEvent(selectedItem);
    }

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        initializeSystemTree();
        initializeIncludeAndExcludeLists();
        intializeResultTable();
    }

    private void initializeIncludeAndExcludeLists() {
        includeToScanList.setCellFactory(getFilePathTreeItemRenderer());
        includeToScanList.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
        excludeFromScanList.setCellFactory(getFilePathTreeItemRenderer());
        excludeFromScanList.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
    }

    private Callback<ListView<FilePathTreeItem>, ListCell<FilePathTreeItem>> getFilePathTreeItemRenderer() {
        return new Callback<ListView<FilePathTreeItem>, ListCell<FilePathTreeItem>>() {
            @Override
            public ListCell<FilePathTreeItem> call(ListView<FilePathTreeItem> p) {
                ListCell<FilePathTreeItem> cell = new ListCell<FilePathTreeItem>() {
                    @Override
                    protected void updateItem(FilePathTreeItem item, boolean bln) {
                        super.updateItem(item, bln);
                        if (item != null) {
                            setText(item.getFullPath());
                        }
                    }
                };
                return cell;
            }
        };
    }

    private void initializeSystemTree() {
        //setup the file browser root
        String hostName = "computer";
        TreeItem<String> rootNode = null;
        try {
            hostName = InetAddress.getLocalHost().getHostName();
            rootNode = new TreeItem<>(hostName, new ImageView(new Image(newInputStream(FileSystems.getDefault().getPath("./src/main/resources/images/computer.png")), 20.0, 20.0, true, true)));
        } catch (IOException x) {
        }
        Iterable<Path> rootDirectories = FileSystems.getDefault().getRootDirectories();
        for (Path name : rootDirectories) {
            FilePathTreeItem treeNode = new FilePathTreeItem(name);
            treeNode.setIndependent(false);
            rootNode.getChildren().add(treeNode);
        }
        rootNode.setExpanded(false);
        systemTree.setRoot(rootNode);
        systemTree.setShowRoot(false);
        systemTree.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
//        systemTree.setCellFactory(CheckBoxTreeCell.<String>forTreeView());
    }
}
